package com.company.编译原理.语法分析;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/**
 * @ClassName DFA624
 * @Description TODO
 * @Author 11
 * @Date 2021/6/24 17:27
 * @Version 1.0
 */
public class DFA624 {

    /*
else	ELSE	1
if		IF		2
switch	SWITCH	3
case	CASE	4
default	DEFAULT	5
int		INT		6
void	VOID	7
struct	STRUCT	8
return	RETURN	9
break	BREAK	10
goto	GOTO	11
while	WHILE	12
for		FOR		13
<		LT		14
<=		LE		15
==		EQ		16
<>		NE		17
>		GT		18
>=		GE		19
=		IS		20
+		PL		21
-		MI		22
*		MU		23
/		DI		24
(		LP		25
)		RP		26
*/
        static String[] keys = {
                " ","else","if","switch","case","default","int","void","struct","return","break","goto","while","for"
        };
        static String[] SYN = {
                " ","ELSE","IF","SWITCH","CASE","DEFAULT","INT","VOID","STRUCT","RETURN","BREAK","GOTO","WHILE","FOR","LT","LE","EQ","NE","GT","GE","IS","PL","MI","MU","DI","LP","RP"
        };//用hashmap优化

        /*查关键字是否存在，每调用一次，就以 TOKEN 中的字符串查保留字表，若查到，返回相应关键字的类别码；否则返回零。*/
        private static int lookup(String a){
        int i;
        for (i = 1; i <= 13; i++) {
            if (a.equals(keys[i])) return i;
        }
        return 0;

    }

        /* 判断是不是字母 */
        private static boolean isletter(Character ch)
        {
            if((ch>='a' && ch<='z') || (ch>='A' && ch<='Z'))
                return true;
            else return false;
        }

        /* 判断是不是数字 */
        private static boolean isdigit(Character ch)
        {
            if(ch>='0' && ch<='9')
                return true;
            else return false;
        }


        public static void main(String[] args) {
        StringBuffer stringBuffer = new StringBuffer();
        BufferedReader reader = null;
        try {
            reader= new BufferedReader(new FileReader("F:\\workProject\\interview-questions\\javacode\\src\\main\\java\\com\\company\\编译原理\\DFA\\test.txt"));
            String tempStr;
            while ((tempStr = reader.readLine()) != null) {
                stringBuffer.append(tempStr);
            }
            reader.close();
            runDFA(stringBuffer);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

        private static void runDFA(StringBuffer inputString) {
        int N = 20;
        Character current_char;//1.当前字符
        int current_state = 0;//2.当前状态
        StringBuffer current_lex = new StringBuffer();//标识符集
        StringBuffer keyword = new StringBuffer();//关键字集
//        Character[] current_lex = new Character[N];
        int i=0;
        int k=0;
        for(int j=0;j < inputString.length();j++) {//遍历字符集

            current_char = inputString.charAt(j);;  //当前字符
                switch (current_state){  //选择当前状态
                case 0://开始
                    if(current_char == ';'){//is a letter 如果是一个字母
                        System.out.println("分号符："+";");
                    }
                    if(isletter(current_char)){//is a letter 如果是一个字母
                        current_state = 1;
                        current_lex.append(current_char);//加入标识符集
                    }
                    if(isdigit(current_char)){//is a digit  数字
                        current_state = 2;
                        current_lex.append(current_char);
//                        current_lex[i] = current_char;
//                        i++;
                    }
                    if(current_char == '+'){// +  加号
                        current_state = 3;
                        current_lex.append(current_char);
                    }
                    if(current_char == '-'){// -减号
                        current_state = 4;
                        current_lex.append(current_char);
//                        current_lex[i] = current_char;
//                        i++;
                    }
                    if(current_char == '>' || current_char == '<' || current_char == '='){// > >=  < <=  = ==
                        current_state = 5;
                        current_lex.append(current_char);
                    }
                    if(current_char == '*'){// '*' 和 "*/"
                        current_state = 11;
                        current_lex.append(current_char);
//                        current_lex[i] = current_char;
//                        i++;
                    }
                    if(current_char == '/'){// '/' 和 "/*"
                        current_state = 7;
                        current_lex.append(current_char);
//                        current_lex[i] = current_char;
//                        i++;
                    }
                    if(current_char == '('){
                        current_state = 9;
                        current_lex.append(current_char);
//                        current_lex[i] = current_char;
//                        i++;
                    }
                    if(current_char == ')'){
                        current_state = 10;
                        current_lex.append(current_char);
//                        current_lex[i] = current_char;
//                        i++;
                    }
                    if(current_state == 0 ){/* 不是token */
                        continue;
                    }
                    break;
                case 1:
                    if(!isletter(current_char)){//如果不是字母  结束判断

//                        current_lex.append(" ");
//                        current_lex[i]=' ';//这个不是字母，存储“ ”
//                        int t = lookup(current_lex.substring(i-k,i));
                        int t = lookup(current_lex.toString());
                        if(t!=0){  //判断是关键字还是标识符
                            System.out.println("关键字："+SYN[t]+" ");

                        }else{
                            System.out.println("标识符："+"ID"+" "+ current_lex.toString());

                        }
                        current_state = 0;
                        current_lex= new StringBuffer();//清除 归0
                        j--;
                    }else{
                        current_lex.append(current_char);  //接上
                    }
                    break;
                case 2:
                    if(!isdigit(current_char)){//如果不是数字
                        System.out.println("数字："+current_lex);

                        current_state = 0;
                        current_lex= new StringBuffer();
                        j--;
                    }else{
                        current_lex.append(current_char);
                    }
                    break;
                case 3:
                    if(current_char!='+'){
                        if(current_char!='='){
                            System.out.println("加号：+");
                            current_state = 0;
                            current_lex= new StringBuffer();
                            j--;
                        }else {
                            current_lex.append(current_char);//+=
                            System.out.println("加等于号：+=");
                            current_state = 0;
                            current_lex= new StringBuffer();
                        }
                    }else{// 应该是++
                        current_lex.append(current_char);//++
                        System.out.println("自增号：++");//结束状态
                        current_state = 0;
                        current_lex= new StringBuffer();
                    }
                    break;
                case 4:
                    if(current_char!='-'){

                        if(current_char!='='){
                            System.out.println("减号：-");
                            current_state = 0;
                            current_lex= new StringBuffer();
                            j--;
                        }else {
                            current_lex.append(current_char);//-=
                            System.out.println("减等于号：-=");
                            current_state = 0;
                            current_lex= new StringBuffer();
                        }

                    }else{// 应该是--
                        current_lex.append(current_char);//--
                        System.out.println("自减号：--");//结束状态
                        current_state = 0;
                        current_lex= new StringBuffer();
                    }
                    break;
                case 5:
                    if(current_char!='=' && !current_char.equals(current_lex.charAt(0))){//避免“>> <<”   左移右移不判断

                        if(current_lex.toString().equals("<"))
                            System.out.println("小于号：<");
                        else if(current_lex.toString().equals(">"))
                            System.out.println("大于号: >");
                        else if(current_lex.toString().equals("="))
                            System.out.println("等号: =");
                        else if(current_lex.toString().equals(">="))
                            System.out.println("大于等于: >=");
                        else if(current_lex.toString().equals("<="))
                            System.out.println("小于等于: <=");
                        else if(current_lex.toString().equals("=="))
                            System.out.println("等等: == ");
                        current_state = 0;
                        current_lex= new StringBuffer();
                        j--;//回退一个字符
                    }else{
                        if (current_lex.length()>2){//>=  再来一个=   变成>==是不符合的  跳出
                            current_state = 0;
                            current_lex= new StringBuffer();
                            break;
                        }
                        current_lex.append(current_char);
                    }
                    break;
                    //----------------------
                case 6:
                    if(current_char !='/'){ /* 不考虑 a*=b  */ //??????    /**a

//                        System.out.println("("+"DI"+","+" "+")");
////                        cout<<"("<<"DI"<<","<<" "<<")"<<endl; 	//单纯的'*' 不是注释
                        current_state = 8;
//                        current_lex= new StringBuffer();
//                        i=0;

                        break;
                    }else{//注释部分结束
                        current_state = 0;
                        current_lex= new StringBuffer();
                        continue;
//                        current_char=fgetc(file);/*这里是注释的结尾*/
                    }
//                    break;
                case 7:
                    if(current_char!='*'){ /* 不考虑 a/=b  */
                        if(current_char!='='){
                            System.out.println("除号: /" );
                            current_state = 0;
                            current_lex= new StringBuffer();
                            j--;
                        }else {
                            current_lex.append(current_char);///=
                            System.out.println("除等于号：/=");
                            current_state = 0;
                            current_lex= new StringBuffer();
                        }
                    }else{//注释部分开始  /*
                        current_state = 8;
                        current_lex= new StringBuffer();
                        continue;
//                        current_char=fgetc(file);	/* 如果是注释部分 就忽略当前字符 再读一个 */
                    }
                    break;
                case 8:
                    if(current_char!='*'){
                        current_state = 8;
                        continue;
//                        current_char=fgetc(file);	/* 如果是注释部分 就忽略当前字符 再读一个 */
                    } else{
                        current_state = 6;
                        continue;
//                        current_char=fgetc(file);	/* 如果是注释部分 就忽略当前字符 再读一个 */
                    }
//                    break;
                case 9:
//                    if(current_char!='('){
                    System.out.println("左括号：( ");
                    current_state = 0;
                    current_lex= new StringBuffer();
                    j--;
////                        i=0;
//                    }else{
//                        current_lex.append(current_char);
////                        i++;
//                    }
                    break;
                case 10:
//                    if(current_char!=')'){
                    System.out.println("右括号：)");
//                        cout<<"("<<"RP"<<","<<" "<<")"<<endl;
                    current_state = 0;
                    current_lex= new StringBuffer();
                    j--;
//                    }else{
//                        current_lex.append(current_char);
//                        i++;
//                    }
                    break;



                case 11:
                    if(current_char!='='){
                        System.out.println("乘号：*");
                        current_state = 0;
                        current_lex= new StringBuffer();
                        j--;
                    }else {
                        current_lex.append(current_char);//-=
                        System.out.println("减等于号：-=");
                        current_state = 0;
                        current_lex= new StringBuffer();
                    }

                    break;
                default: break;
//                    System.out.println();
            }

        }

    }

}
